/*
 * IntegerField.java
 *
 * Created on 13 November 2006, 10:36
 */

package org.foment.joliage3.newt;

import java.awt.Dimension;
import java.text.ParseException;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

/**
 *
 * @author  ivan
 */
public class IntegerField extends javax.swing.JPanel {
  
  public class TimerThread extends Thread {
    private int _change = 0;
    private boolean _running = false;
    
    public void setChange(int change) {
      _change = change;
    }
    
    public void halt() {
      _running = false;
    }
    
    public void run() {
      int sleepTime = 500;
      _running = true;
      while (_running) {
        try {
          if (_change != 0)
            setValue(getValue() + _change);
          if (sleepTime == 500) sleepTime = 200;
          else if (sleepTime > 100) sleepTime -= 10;
          sleep(sleepTime);
        } catch (InterruptedException ex) {
          ex.printStackTrace();
        }
      }
    }
  };
  
  TimerThread timer;
  
  /** Creates new form BeanForm */
  public IntegerField() {
    initComponents();
    setBorder(txtValue.getBorder());
    txtValue.setBorder(null);
    
    txtValue.setText(String.valueOf(_value));
    
  }

  /* sets minimum and maximum allowed values */
  public void setLimit(int min, int max) {

      _minimum = min;
      _maximum = max;

      _useMaximum = true;
      _useMinimum = true;
  }
  
  /** This method is called from within the constructor to
   * initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is
   * always regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
  private void initComponents() {
    txtValue = new javax.swing.JFormattedTextField();
    btnIncrease = new javax.swing.JLabel();
    btnDecrease = new javax.swing.JLabel();

    setLayout(new java.awt.BorderLayout());

    setPreferredSize(new java.awt.Dimension(44, 19));
    txtValue.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
    txtValue.setText("0");
    txtValue.setFormatterFactory(new javax.swing.JFormattedTextField.AbstractFormatterFactory() {
      public javax.swing.JFormattedTextField.AbstractFormatter getFormatter(javax.swing.JFormattedTextField tf) {
        return new javax.swing.text.NumberFormatter(java.text.NumberFormat.getIntegerInstance());
      }
    });
    txtValue.addFocusListener(new java.awt.event.FocusAdapter() {
      public void focusLost(java.awt.event.FocusEvent evt) {
        txtValueFocusLost(evt);
      }
    });
    txtValue.addMouseWheelListener(new java.awt.event.MouseWheelListener() {
      public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) {
        txtValueMouseWheelMoved(evt);
      }
    });

    add(txtValue, java.awt.BorderLayout.CENTER);

    btnIncrease.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
    btnIncrease.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/foment/joliage3/newt/images/arrow_right.png")));
    btnIncrease.setBorder(javax.swing.BorderFactory.createCompoundBorder(javax.swing.BorderFactory.createMatteBorder(0, 1, 0, 0, new java.awt.Color(102, 102, 102)), javax.swing.BorderFactory.createEmptyBorder(0, 4, 0, 0)));
    btnIncrease.addMouseListener(new java.awt.event.MouseAdapter() {
      public void mousePressed(java.awt.event.MouseEvent evt) {
        btnIncreaseMousePressed(evt);
      }
      public void mouseReleased(java.awt.event.MouseEvent evt) {
        btnIncreaseMouseReleased(evt);
      }
    });

    add(btnIncrease, java.awt.BorderLayout.LINE_END);

    btnDecrease.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/foment/joliage3/newt/images/arrow_left.png")));
    btnDecrease.setBorder(javax.swing.BorderFactory.createCompoundBorder(javax.swing.BorderFactory.createMatteBorder(0, 0, 0, 1, new java.awt.Color(102, 102, 102)), javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 4)));
    btnDecrease.addMouseListener(new java.awt.event.MouseAdapter() {
      public void mousePressed(java.awt.event.MouseEvent evt) {
        btnDecreaseMousePressed(evt);
      }
      public void mouseReleased(java.awt.event.MouseEvent evt) {
        btnDecreaseMouseReleased(evt);
      }
    });

    add(btnDecrease, java.awt.BorderLayout.LINE_START);

  }// </editor-fold>//GEN-END:initComponents

  private void txtValueMouseWheelMoved(java.awt.event.MouseWheelEvent evt) {//GEN-FIRST:event_txtValueMouseWheelMoved
    setValue(getValue() - evt.getWheelRotation());
  }//GEN-LAST:event_txtValueMouseWheelMoved

  public void startTimer(int change) {
    timer = new TimerThread();
    timer.setChange(change);
    timer.start();
  }
  
  public void stopTimer() {
    if (timer == null) return;
    timer.halt();
    timer = null;
  }
  
  private void btnIncreaseMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btnIncreaseMouseReleased
    stopTimer();
  }//GEN-LAST:event_btnIncreaseMouseReleased

  private void btnDecreaseMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btnDecreaseMouseReleased
    stopTimer();
  }//GEN-LAST:event_btnDecreaseMouseReleased

  private void btnIncreaseMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btnIncreaseMousePressed
    //setValue(getValue() + 1);
    txtValue.requestFocus();
    startTimer(1);
  }//GEN-LAST:event_btnIncreaseMousePressed

  private void btnDecreaseMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btnDecreaseMousePressed
    //setValue(getValue() - 1);
    txtValue.requestFocus();
    startTimer(-1);
  }//GEN-LAST:event_btnDecreaseMousePressed

  private void txtValueFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtValueFocusLost
    try {
      setValue(java.text.NumberFormat.getIntegerInstance().parse(txtValue.getText()).intValue());
    } catch (ParseException ex) {
      
      txtValue.setText(java.text.NumberFormat.getIntegerInstance().format(_value));
    }
  }//GEN-LAST:event_txtValueFocusLost
  
  
  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JLabel btnDecrease;
  private javax.swing.JLabel btnIncrease;
  private javax.swing.JFormattedTextField txtValue;
  // End of variables declaration//GEN-END:variables

  /**
   * Holds _value of property _value.
   */
  private int _value = 0;
  private int _minimum = 0;
  private int _maximum = 100;
  private boolean _useMaximum = false;
  private boolean _useMinimum = false;

  /**
   * Utility field used by bound properties.
   */
  private java.beans.PropertyChangeSupport propertyChangeSupport =  new java.beans.PropertyChangeSupport(this);

  /**
   * Utility field used by constrained properties.
   */
  private java.beans.VetoableChangeSupport vetoableChangeSupport =  new java.beans.VetoableChangeSupport(this);

  /**
   * Adds a PropertyChangeListener to the listener list.
   * @param l The listener to add.
   */
  public void addPropertyChangeListener(java.beans.PropertyChangeListener l) {
    propertyChangeSupport.addPropertyChangeListener(l);
  }

  /**
   * Removes a PropertyChangeListener from the listener list.
   * @param l The listener to remove.
   */
  public void removePropertyChangeListener(java.beans.PropertyChangeListener l) {
    propertyChangeSupport.removePropertyChangeListener(l);
  }

  /**
   * Getter for property value.
   * @return Value of property value.
   */
  public int getValue() {
    return _value;
  }

  /**
   * Setter for property value.
   * 
   * @param value New _value of property value.
   * @throws PropertyVetoException if some vetoable listeners reject the new _value
   */
  public void setValue(int value) {
    int oldValue = _value;
    if (_useMinimum && value < _minimum) value = _minimum;
    if (_useMaximum && value > _maximum) value = _maximum;
    _value = value;
    txtValue.setText(String.valueOf(value));
    propertyChangeSupport.firePropertyChange ("value", new Integer (oldValue), new Integer (value));
  }

  /**
   * Getter for property minimumValue.
   * @return Value of property minimumValue.
   */
  public int getMinimum() {
    return _minimum;
  }

  /**
   * Setter for property minimumValue.
   * 
   * @param minimumValue New _value of property minimumValue.
   */
  public void setMinimum(int minimum) {
    _minimum = minimum;
    if (_useMinimum && _value < _minimum) setValue(_minimum);
  }

  /**
   * Getter for property _maximum.
   * 
   * @return Value of property _maximum.
   */
  public int getMaximum() {
    return _maximum;
  }

  /**
   * Setter for property _maximum.
   * 
   * @param _maximum New _value of property _maximum.
   */
  public void setMaximum(int maximum) {
    _maximum = maximum;
    if (_useMaximum && _value > _maximum) setValue(_maximum);
  }

  /**
   * Getter for property _useMinimum.
   * 
   * @return Value of property _useMinimum.
   */
  public boolean isUsingMinimum() {
    return _useMinimum;
  }

  /**
   * Setter for property _useMinimum.
   * 
   * @param _useMinimum New _value of property _useMinimum.
   */
  public void setUsingMinimum(boolean useMinimum) {
    _useMinimum = useMinimum;
    if (_useMinimum && _value < _minimum) setValue(_minimum);
  }

  /**
   * Getter for property _useMaximum.
   * 
   * @return Value of property _useMaximum.
   */
  public boolean isUsingMaximum() {
    return _useMaximum;
  }

  /**
   * Setter for property _useMaximum.
   * 
   * @param _useMaximum New _value of property _useMaximum.
   */
  public void setUsingMaximum(boolean useMaximum) {
    _useMaximum = useMaximum;
    if (_useMaximum && _value > _maximum) setValue(_maximum);
  }
  
}
